package com.tansun.easycare.rule.bakproject.service.impl;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileWriter;
import java.sql.SQLException;
import java.util.List;
import java.util.Properties;

import javax.sql.DataSource;

import org.dbunit.DatabaseUnitException;
import org.dbunit.database.DatabaseConfig;
import org.dbunit.database.DatabaseConnection;
import org.dbunit.database.ForwardOnlyResultSetTableFactory;
import org.dbunit.database.IDatabaseConnection;
import org.dbunit.database.QueryDataSet;
import org.dbunit.dataset.IDataSet;
import org.dbunit.dataset.xml.FlatXmlDataSet;
import org.dbunit.dataset.xml.FlatXmlDataSetBuilder;
import org.dbunit.ext.db2.Db2DataTypeFactory;
import org.dbunit.ext.db2.Db2MetadataHandler;
import org.dbunit.ext.mysql.MySqlDataTypeFactory;
import org.dbunit.ext.mysql.MySqlMetadataHandler;
import org.dbunit.ext.oracle.OracleDataTypeFactory;
import org.dbunit.ext.postgresql.PostgresqlDataTypeFactory;
import org.dbunit.operation.CompositeOperation;
import org.dbunit.operation.DatabaseOperation;
import org.dbunit.operation.RuleProjectDeleteOperation;
import org.drools.core.util.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.xml.sax.InputSource;

import com.tansun.easycare.core.config.Global;
import com.tansun.easycare.rule.bakproject.service.IRuleProjetBakService;
import com.tansun.easycare.rule.bakproject.service.RuleBakTableConst;
import com.tansun.easycare.rule.exception.BizException;
import com.tansun.rule.utils.LoggerManager;

@Service
public class RuleProjectBakServiceImpl implements IRuleProjetBakService {
	
	@Autowired
	//@Qualifier("springDataSource")
	private   DataSource  springDataSource;

	@Override
	public void bakRuleProject(String projectCode) throws BizException {
		   try {
		       IDatabaseConnection conn = createDataConnection();
		       DatabaseConfig  dataConfig = conn.getConfig();
		       setDataConfig(dataConfig);
		       String  encode  = Global.getConfig("RuleProject.Back.Encoding");
		       QueryDataSet  dataSet  = null;
		       List<String> tables =RuleBakTableConst.readRuleTable();
		       String  sql ="";
		       String  ruleBakPath  = Global.getConfig("RuleProject.BakPath")+File.separator+projectCode;
		       File  file  = new  File(ruleBakPath);
		       if (file.exists()) {
		    	   file.delete();
		       }
		       file.mkdirs();
		       int num = tables.size();
		       for (String  tablename :tables) {
		    	   try {
			    	 if (tablename.toLowerCase().equals("rule_versioninfo")|| tablename.toLowerCase().equals("rule_flow")
			    			 || tablename.toLowerCase().equals("rule_group")|| tablename.toLowerCase().equals("rule_codeblock")) {
			    		 dataConfig.setProperty(DatabaseConfig.PROPERTY_RESULTSET_TABLE_FACTORY, new ForwardOnlyResultSetTableFactory()); 
			    	 }
		    		 if (tablename.toLowerCase().equals("rule_dataset") || tablename.toLowerCase().equals("rule_project") 
		    				 ||tablename.toLowerCase().equals("rule_dataparams") ||tablename.toLowerCase().equals("rule_authority") ) {
			    		 sql = "select  *   from "+tablename+"  where projectcode='"+projectCode +"'"; 
			    	 }else if (tablename.toLowerCase().equals("rule_data_domain")) {
			    		 sql = "select  a.*   from "+tablename+" a , rule_dataparams  b  where  a.DOMAIN_ID = b.ID and  b.projectcode='"+projectCode +"'"; 
			    	 }else {
			    	   sql = "select  *   from "+tablename+"  where project_code='"+projectCode +"'"; 
			    	 }
			    	 dataSet  = new QueryDataSet(conn); 
			    
			         dataSet.addTable(tablename,sql);
				       if (StringUtils.isEmpty(encode)) {
				        	 encode ="UTF-8";
				       }
			         FlatXmlDataSet.write(dataSet, new FileWriter(ruleBakPath+File.separator+tablename+".xml"),encode);
			         num--;
			         System.out.println("项目："+projectCode+"导出表["+tablename+"]完成,剩下表【"+num+"】张");
		    	   }catch(Exception e) {
		    		   System.out.println("项目："+projectCode+"导出表["+tablename+"]异常:"+e.getMessage());
					   continue;
				   }
		       }
		     
		   }catch(Exception e) {
			   throw   new  BizException(e,"E-005001");
			   
		   }

	}

	@Override
	public void restoreRuleProject(String projectCode,String dataOprType) throws BizException {
		   try {
		       IDatabaseConnection conn = createDataConnection();
		       DatabaseConfig  dataConfig = conn.getConfig();
		       setDataConfig(dataConfig);
		       String  encode  = Global.getConfig("RuleProject.Back.Encoding");
		       List<String> tables =RuleBakTableConst.readRuleTable();
		       String  ruleBakPath  = Global.getConfig("RuleProject.BakPath")+File.separator+projectCode;
		       File  file  = new  File(ruleBakPath);
		       if (!file.exists()) {
		    	   throw   new  BizException("E-005001");
		       }
		      
		       FileInputStream  fis  = null;
		       InputSource  inputSource = null;
		       int num = tables.size();
		       for (String  tablename :tables) {
			       if (tablename.toLowerCase().equals("rule_versioninfo")|| tablename.toLowerCase().equals("rule_flow")
			    			 || tablename.toLowerCase().equals("rule_group")|| tablename.toLowerCase().equals("rule_codeblock")) {
			    		 dataConfig.setProperty(DatabaseConfig.PROPERTY_RESULTSET_TABLE_FACTORY, new ForwardOnlyResultSetTableFactory()); 
			       }
			       DatabaseOperation databaseOperation  = null;
			       if (dataOprType != null && dataOprType.toUpperCase().equals("INSERT")) {
			    	   databaseOperation= DatabaseOperation.INSERT; 
			       }else if (dataOprType != null && dataOprType.toUpperCase().equals("REFRESH")) {
			    	   databaseOperation= DatabaseOperation.REFRESH; 
			       }
			       else {
			    	   /* databaseOperation= DatabaseOperation.CLEAN_INSERT;*/ //:删除所有的数据表中的数据,然后插入数据集中定义的数据,
			    	   databaseOperation= new CompositeOperation(new RuleProjectDeleteOperation(),DatabaseOperation.INSERT);  //删除数据集中存在的数据行 
			       }
			       try {
				       FlatXmlDataSetBuilder builder = new FlatXmlDataSetBuilder();
				       builder.setColumnSensing(true);
				       fis = new FileInputStream(ruleBakPath+File.separator+tablename+".xml");
				       inputSource =new InputSource(fis);
				       // InputSource  inputSource  = new InputSource(new FileInputStream(ruleBakPath+File.separator+tablename+".xml"));
				       if (encode == null) {
				        	 encode ="UTF-8";
				       }
				       inputSource.setEncoding(encode);
				       IDataSet ds =  builder.build(inputSource);
				       DatabaseOperation  commOperation = DatabaseOperation.TRANSACTION(databaseOperation);
				       commOperation.execute(conn, ds);
				       DatabaseOperation.CLOSE_CONNECTION(commOperation);
				       num--;
				       System.out.println("项目："+projectCode+"数据导入表["+tablename+"]完成,剩余表【"+num+"】张");
			       }catch (FileNotFoundException e) {
			    	   continue;
					// TODO: handle exception
			       }finally {
			    	   if (fis != null) {
			    		   fis.close();
			    	   }
			       }
			      
		       }
		       
		     
		   }catch(Exception e) {
			   LoggerManager.error(e.getMessage(), e,this.getClass());
			   throw   new  RuntimeException(e);
			   
		   }
		
	}
	
	
	private   IDatabaseConnection    createDataConnection() throws DatabaseUnitException, SQLException {
		   IDatabaseConnection conn = null;
		   String  type = Global.getConfig("jdbc.type");
	       if (type.equals("oracle")) {
	    	  String  username = Global.getConfig("jdbc.username"); 
	          conn =new DatabaseConnection(springDataSource.getConnection(),username);
	       }else if (type.equals("postgre")) {
	    	   String schema=Global.getConfig("RuleProject.res.schema");
	    	   conn =new DatabaseConnection(springDataSource.getConnection(),schema); 		    	   
	       }else if (type.equals("mysql")) {
	    	   conn =new DatabaseConnection(springDataSource.getConnection()); 
	       }else if (type.equals("db2")) {
	    	   String schema=Global.getConfig("RuleProject.res.schema");
	    	   conn =new DatabaseConnection(springDataSource.getConnection(),schema);
	       }else {
	    	   conn =new DatabaseConnection(springDataSource.getConnection()); 
	       }
	       return  conn;
	}
	
	
	private void setDataConfig(DatabaseConfig  dataConfig) {
		   String type = Global.getConfig("jdbc.type"); 
		   if (type.equals("mysql")) {
			   dataConfig.setProperty(DatabaseConfig.PROPERTY_METADATA_HANDLER,new MySqlMetadataHandler());
			   dataConfig.setProperty(DatabaseConfig.PROPERTY_DATATYPE_FACTORY, new MySqlDataTypeFactory());
		   }else if (type.equals("oracle")) {
			   dataConfig.setProperty(DatabaseConfig.PROPERTY_DATATYPE_FACTORY, new OracleDataTypeFactory());
		   }else if (type.equals("postgre")) {
			   dataConfig.setProperty(DatabaseConfig.PROPERTY_DATATYPE_FACTORY, new PostgresqlDataTypeFactory());
		   }else if (type.equals("db2")) {
	    	   dataConfig.setProperty(DatabaseConfig.PROPERTY_METADATA_HANDLER,new Db2MetadataHandler());
	    	   dataConfig.setProperty(DatabaseConfig.PROPERTY_DATATYPE_FACTORY,new Db2DataTypeFactory());
	       }
	}
	
	public static void main(String[] args) {

	}

}
